package net.chasing.androidbaseconfig.view;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Window;

import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import com.hwangjr.rxbus.RxBus;

import net.chasing.androidbaseconfig.R;
import net.chasing.androidbaseconfig.util.CollectionUtils;
import net.chasing.androidbaseconfig.util.L;
import net.chasing.androidbaseconfig.util.OneClickUtil;
import net.chasing.androidbaseconfig.util.permission.PermissionUtils;
import net.chasing.androidbaseconfig.util.StatusBarUtil;
import net.chasing.androidbaseconfig.widget.dialog.ProgressDialog;

import java.util.ArrayList;
import java.util.List;

/**
 * 注：所有的延迟操作，操作内使用到binding的都需要进行判断 !=null，因为可能在延迟内Aty销毁binding置null了
 *
 * @param <Binding> 试图binding
 */
public abstract class BaseMVCActivity<Binding extends ViewDataBinding>
        extends AppCompatActivity {
    protected OneClickUtil mOneClickUtil;
    protected Context mContext;

    protected boolean isCreateBySavedInstanceState = false;
    protected boolean needChangeStatusBar = true;
    protected boolean isTransparent = false;
    protected boolean isFullScreen = false;
    protected boolean isDarkMode = true;
    protected boolean isNewIntent = false;
    protected int mStatusBarColor = android.R.color.white;

    private ProgressDialog dialog;
    protected Binding mBinding;

    //保存所有Fragment实例，避免重复创建，注意put方法不得早于changeFragmentToShow方法调用
    protected Handler mHandler = new Handler(Looper.getMainLooper());
    protected List<IActivityLifecycleCallback> mLifecycleCallbackList = new ArrayList<>();

    //统一判断，避免连续打开两个界面
    protected static void start(Context context, Class<?> clazz) {
        start(context, clazz, true);
    }

    protected static void start(Context context, Class<?> clazz, boolean changeAnim) {
        start(context, new Intent(context, clazz), changeAnim);
    }

    protected static void start(Context context, Intent intent) {
        start(context, intent, true);
    }

    protected static void start(Context context, Intent intent, boolean changeAnim) {
        context.startActivity(intent);
        if (changeAnim)
            if (context instanceof Activity)
                ((Activity) context).overridePendingTransition(R.anim.slide_right_in, R.anim.slide_left_out_20p);
    }

    protected static void startForResult(Activity activity, Intent intent, int requestCode) {
        activity.startActivityForResult(intent, requestCode);
        activity.overridePendingTransition(R.anim.slide_right_in, R.anim.slide_left_out_20p);
    }

    // 让activity的回调传递到fragment
    protected static void startForResult(Activity activity, Fragment fragment, Intent intent, int requestCode) {
        fragment.startActivityForResult(intent, requestCode);
        activity.overridePendingTransition(R.anim.slide_right_in, R.anim.slide_left_out_20p);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);

        // 以下方式会导致小组件异常
//        int flag=getIntent().getFlags();
//        if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
//            //完美解决：APP下载安装后，直接点击“打开”，启动应用后，按下HOME键，再次点击桌面上的应用，会重启一个新的应用问题
//            finish();
//            return;
//        }

        if (savedInstanceState != null) {
            isCreateBySavedInstanceState = true;
        }

        mContext = this;
        initBeforeOnCreate(savedInstanceState);
        if (needChangeStatusBar) {
            if (isFullScreen)
                StatusBarUtil.setFullScreen(this);
            else if (isTransparent)
                StatusBarUtil.setTransparentStatusBar(this, true);
            else
                StatusBarUtil.setStatusBar(this, ContextCompat.getColor(this, mStatusBarColor), isDarkMode);
        }

        mOneClickUtil = new OneClickUtil();

        mBinding = DataBindingUtil.setContentView(this, bindLayout());
        mBinding.setLifecycleOwner(this);

        initView();
        setListener();
    }

    protected void initBeforeOnCreate(@Nullable Bundle savedInstanceState) {

    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        isNewIntent = true;
        setIntent(intent);
    }

    protected abstract int bindLayout();

    protected abstract void initView();

    protected abstract void setListener();

    public void registerLifecycle(IActivityLifecycleCallback lifecycleCallback) {
        mLifecycleCallbackList.add(lifecycleCallback);
    }

    public void unregisterLifecycle(IActivityLifecycleCallback lifecycleCallback) {
        mLifecycleCallbackList.remove(lifecycleCallback);
    }

    @Override
    public void onConfigurationChanged(@NonNull Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (!mOneClickUtil.check("changeUISize")) {
            changeUISize(true);
        }
    }

    @Override
    protected void onStart() {
        List<IActivityLifecycleCallback> temp = new ArrayList<>(mLifecycleCallbackList);
        if (CollectionUtils.isNotEmpty(temp)) {
            for (IActivityLifecycleCallback callback : temp) {
                callback.onStart();
            }
        }
        super.onStart();
    }

    @Override
    protected void onResume() {
        List<IActivityLifecycleCallback> temp = new ArrayList<>(mLifecycleCallbackList);
        if (CollectionUtils.isNotEmpty(temp)) {
            for (IActivityLifecycleCallback callback : temp) {
                callback.onResume();
            }
        }
        super.onResume();
        if (!mOneClickUtil.check("changeUISize")) {
            changeUISize(false);
        }
    }

    @Override
    protected void onPause() {
        List<IActivityLifecycleCallback> temp = new ArrayList<>(mLifecycleCallbackList);
        if (CollectionUtils.isNotEmpty(temp)) {
            for (IActivityLifecycleCallback callback : temp) {
                callback.onPause();
            }
        }
        super.onPause();
    }

    @Override
    protected void onStop() {
        List<IActivityLifecycleCallback> temp = new ArrayList<>(mLifecycleCallbackList);
        if (CollectionUtils.isNotEmpty(temp)) {
            for (IActivityLifecycleCallback callback : temp) {
                callback.onStop();
            }
        }
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        if (mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
            mHandler = null;
        }
        mBinding = null;
        List<IActivityLifecycleCallback> temp = new ArrayList<>(mLifecycleCallbackList);
        if (CollectionUtils.isNotEmpty(temp)) {
            for (IActivityLifecycleCallback callback : temp) {
                callback.onDestroy();
            }
        }
        mLifecycleCallbackList.clear();
        super.onDestroy();
    }

    protected void changeUISize(boolean isByChangeConfiguration) {

    }

    // 移除所有fragment，如果fragment嵌套fragment，则还需要移除子fragment，避免FragmentManager一直保存着旧界面
    protected void removeAllFragment() {
        if (mOneClickUtil == null || mOneClickUtil.check("removeAllFragment" + this)) return;
        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment;
        List<Fragment> fragments = fm.getFragments();
        for (int i = 0; i < fragments.size(); i++) {
            fragment = fragments.get(i);
            if (fragment != null) {
                if (fragment instanceof BaseFragment)
                    ((BaseFragment<?, ?>) fragment).removeAllFragment();
                fm.beginTransaction().remove(fragment).commitAllowingStateLoss();
                fm.executePendingTransactions();
            }
        }
    }

    /**
     * 添加新的fragment进行显示，并push到fragment栈中
     * 需要控制fragment层级
     *
     * @param resId        布局id
     * @param showFragment 要显示的fragment
     */
    public void addFragmentToShow(@IdRes int resId, Fragment showFragment) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (showFragment.isAdded()) //添加之前判断是否添加过，添加过则移除之前的，重新添加
            transaction.remove(showFragment);

        transaction.add(resId, showFragment);//用的remove不是hide，所以每次均需add
        if (!isFinishing()) {
            transaction.commitAllowingStateLoss();
            getSupportFragmentManager().executePendingTransactions();
        }
    }

    /**
     * 切换要显示的fragment，不进行push到fragment栈
     * 不控制fragment层级
     *
     * @param resId        布局id
     * @param showFragment 要显示的fragment
     */
    public void changeFragmentToShow(@IdRes int resId, Fragment showFragment, String showFragmentTag) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        List<Fragment> fragments = fragmentManager.getFragments();
        for (Fragment fragment : fragments) { // 隐藏所有的fragment
            transaction.hide(fragment);
        }

        if (showFragment.isAdded()) {
            transaction.show(showFragment);
            if (!isFinishing()) {
                transaction.commitAllowingStateLoss();
                fragmentManager.executePendingTransactions();
            }
        } else {
            try {
                Fragment fragmentByTag = fragmentManager.findFragmentByTag(showFragmentTag);
                if (fragmentByTag != null)
                    transaction.remove(fragmentByTag);
                transaction.add(resId, showFragment, showFragmentTag);
                transaction.show(showFragment);
                if (!isFinishing()) {
                    transaction.commitAllowingStateLoss();
                    fragmentManager.executePendingTransactions();
                }
            } catch (Exception e) {
                transaction = fragmentManager.beginTransaction();
                transaction.show(showFragment);
                transaction.commitAllowingStateLoss();
                fragmentManager.executePendingTransactions();
            }
        }
    }

    public void replaceFragmentToShow(@IdRes int resId, Fragment showFragment) {
        if (!isFinishing()) {
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.replace(resId, showFragment);
            transaction.commit();
        }
    }

    private long showLoadingTime;

    public void showLoading() {
        if (isFinishing()) return;
        if (dialog != null && dialog.isShowing()) return;

        FragmentManager fg = getSupportFragmentManager();
        FragmentTransaction ft = fg.beginTransaction();
        if (dialog == null) {
            dialog = new ProgressDialog();
            dialog.setCancelable(true);
        }
        dialog.show(ft, getClass().getName());
        showLoadingTime = System.currentTimeMillis();
    }

    /*
    如果showLoading的时间与hideLoading的时间相差太接近可能导致在调用dismiss的时候dialog还没有正真显示出来
    而dismiss之后dialog才正真显示出来，所以进行时间差判断（如果相差0.3s内就调用hide则延迟处理）
    */
    public void hideLoading() {
        if (dialog != null && !isFinishing()) {
            long time = System.currentTimeMillis();
            if (time - showLoadingTime < 300 && mHandler != null) {
                mHandler.postDelayed(() -> {
                    if (dialog != null && !isFinishing()) {
                        dialog.dismiss();
                        dialog.onDestroy();
                        dialog = null;
                    }
                }, 300 - (time - showLoadingTime));
            } else {
                dialog.dismiss();
                dialog.onDestroy();
                dialog = null;
            }
        }
    }

    @Override
    public void finish() {
        super.finish();
        overridePendingTransition(R.anim.slide_left_in_20p, R.anim.slide_right_out);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        for (int i = 0; i < permissions.length; i++) {
            if (grantResults[i] == PackageManager.PERMISSION_GRANTED)
                onPermissionGrant(permissions[i]);
            else
                onPermissionDeny(permissions[i]);
        }
    }

    private long preGrantStorageTime;

    public void onPermissionGrant(String permission) {
        if (permission != null) {
            boolean isStorage = false;
            if (permission.equals(Manifest.permission.WRITE_EXTERNAL_STORAGE) ||
                    permission.equals(Manifest.permission.READ_EXTERNAL_STORAGE) ||
                    permission.equals(Manifest.permission.READ_MEDIA_IMAGES) ||
                    permission.equals(Manifest.permission.READ_MEDIA_VIDEO) ||
                    permission.equals(Manifest.permission.READ_MEDIA_AUDIO)) {
                isStorage = PermissionUtils.checkStoragePermission(this);
            }
            if (isStorage) {
                long curTime = System.currentTimeMillis();
                if (curTime - preGrantStorageTime >= 10000) {
                    preGrantStorageTime = curTime;
                    RxBus.get().post("StoragePermission", true);
                    L.d("发布权限事件", "走了");
                }
            }
        }
        Fragment fragment;
        List<Fragment> fragments = getSupportFragmentManager().getFragments();
        for (int i = 0; i < fragments.size(); i++) {
            fragment = fragments.get(i);
            if (fragment instanceof BaseFragment)
                ((BaseFragment<?, ?>) fragment).onPermissionGrant(permission);
        }
    }

    public void onPermissionDeny(String permission) {
        if (permission.equals(Manifest.permission.WRITE_EXTERNAL_STORAGE) ||
                permission.equals(Manifest.permission.READ_EXTERNAL_STORAGE) ||
                permission.equals(Manifest.permission.READ_MEDIA_IMAGES) ||
                permission.equals(Manifest.permission.READ_MEDIA_VIDEO) ||
                permission.equals(Manifest.permission.READ_MEDIA_AUDIO)) {
            RxBus.get().post("StoragePermission", false);
        }
        Fragment fragment;
        List<Fragment> fragments = getSupportFragmentManager().getFragments();
        for (int i = 0; i < fragments.size(); i++) {
            fragment = fragments.get(i);
            if (fragment instanceof BaseFragment)
                ((BaseFragment<?, ?>) fragment).onPermissionDeny(permission);
        }
    }
}
